package com.fcat.common.fdfs.controller;

import com.alibaba.fastjson.JSONObject;
import com.netflix.discovery.converters.Auto;
import com.fcat.base.common.util.ArrayUtil;
import com.fcat.base.common.util.StrUtil;
import com.fcat.base.common.util.UUIDUtils;
import com.fcat.common.fdfs.entity.File;
import com.fcat.common.fdfs.entity.Folder;
import com.fcat.common.fdfs.service.FileService;
import com.fcat.common.fdfs.service.FolderService;
import com.fcat.common.fdfs.service.impl.FastDfsServiceImpl;
import com.fcat.common.fdfs.service.impl.LocaleMessageSourceServiceImpl;
import com.fcat.common.fdfs.vo.FolderVO;
import com.fcat.springboot.mybatis.service.BaseService;
import com.fcat.springboot.mybatis.util.JsonUtil;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.io.FilenameUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.*;
import java.util.stream.Collectors;

@RestController
@RequestMapping("file")
public class FileController {
    @Autowired
    private LocaleMessageSourceServiceImpl localeMessageSourceService;
    @Autowired
    private FastDfsServiceImpl dfsClient;
    @Resource
    private FileService fileService;
    @Autowired
    private FolderService folderService;

    @ApiOperation("uploadFile")
    @RequestMapping(value = "/uploadFile", method = RequestMethod.POST)
    public JSONObject uploadFile(@RequestParam("file") MultipartFile file, @RequestParam("fileDir") String fileDir, Long folderId) throws Exception {
        if (file.isEmpty()) {
//            throw new Exception(localeMessageSourceService.getMessage("uploadFileIsNotNull"));
            return JsonUtil.getFailJsonObject("文件为空");
        }
        if(StrUtil.isBlank(FilenameUtils.getExtension(file.getOriginalFilename()))){
            return JsonUtil.getFailJsonObject("文件扩展名不能为空");
        }
        String fileUrl = dfsClient.uploadFile(file);

        File fd = new File();
        fd.setId(UUIDUtils.generateShortUuid());
        fd.setCreateDate(new Date());
        fd.setFileSize(String.valueOf(file.getSize()));
        fd.setName(file.getOriginalFilename());
        fd.setFileExt(FilenameUtils.getExtension(file.getOriginalFilename()));
        if (!StrUtil.isBlank(fileDir)) {
            fd.setFolderId(folderId);
        }
        fd.setFileUrl(fileUrl);
        fileService.insert(fd);

        return JsonUtil.getSuccessJsonObject(fd);
    }

    /**
     * 针对word文件中图标的下载
     * @param fileId
     * @param response
     * @return
     */
    @ApiOperation("downloadFileForEhart")
    @RequestMapping(value = "/downloadFileForEhart", method = RequestMethod.GET)
    public JSONObject downloadFileForEhart(@RequestParam("fileId") String fileId, HttpServletResponse response) {
        if (StrUtil.isBlank(fileId)) {
            return JsonUtil.getFailJsonObject(localeMessageSourceService.getMessage("paramError"));
        }
        File file = fileService.selectById(fileId);
        if (file == null) {
            return JsonUtil.getFailJsonObject(localeMessageSourceService.getMessage("fileNotExist"));
        }
        byte[] content = dfsClient.downloadFile(file.getFileUrl());

        if (content.length > 0) {
            response.setContentType("application/force-download");// 设置强制下载不打开
            try {
                response.addHeader("Content-Disposition", "attachment;fileName=" + new String(file.getName().getBytes("UTF-8"), "iso-8859-1"));// 设置文件名
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            try {
                OutputStream os = response.getOutputStream();
                os.write(content);
                os.flush();
                os.close();
                return JsonUtil.getSuccessJsonObject();
            } catch (Exception e) {
                e.printStackTrace();
                return JsonUtil.getFailJsonObject();
            }
        }
        return JsonUtil.getSuccessJsonObject();
    }

    @ApiOperation("downloadFilexxx")
    @RequestMapping(value = "/downloadFilexxx", method = RequestMethod.GET)
    public JSONObject downloadFile(@RequestParam("fileId") String fileId, HttpServletResponse response, HttpServletRequest request) {
        if (StrUtil.isBlank(fileId)) {
            return JsonUtil.getFailJsonObject(localeMessageSourceService.getMessage("paramError"));
        }
        File file = fileService.selectById(fileId);
        if (file == null) {
            return JsonUtil.getFailJsonObject(localeMessageSourceService.getMessage("fileNotExist"));
        }
        byte[] content = dfsClient.downloadFile(file.getFileUrl());

        Long downloadSize = Long.valueOf(content.length);

        if (content.length > 0) {
            response.setContentType("application/force-download");// 设置强制下载不打开
            ServletContext servletContext = request.getServletContext();
            String mimeType = servletContext.getMimeType(file.getFileUrl());
            if (mimeType == null) {
                mimeType = "application/octet-stream";
            }
            response.setContentType(mimeType);


            // set headers for the response
            String headerKey = "Content-Disposition";
            String headerValue = null;// 设置文件名
            try {
                // headerValue = String.format("attachment; filename=\"%s\"", new String(file.getName().getBytes("UTF-8"), "iso-8859-1"));
                headerValue = String.format("attachment; filename=%s", URLEncoder.encode(file.getName(),"utf-8"));
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            response.setHeader(headerKey, headerValue);
            response.setHeader("Accept-Ranges", "bytes");
            long fromPos = 0, toPos = 0;
            if (request.getHeader("Range") == null) {
                response.setHeader("Content-Length", downloadSize + "");
            } else {
                // 若客户端传来Range，说明之前下载了一部分，设置206状态(SC_PARTIAL_CONTENT)
                response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
                String range = request.getHeader("Range");
                String bytes = range.replaceAll("bytes=", "");
                String[] ary = bytes.split("-");
                fromPos = Long.parseLong(ary[0]);
                if (ary.length == 2) {
                    toPos = Long.parseLong(ary[1]);
                }
                int size;
                if (toPos > fromPos) {
                    size = (int) (toPos - fromPos);
                } else {
                    size = (int) (downloadSize - fromPos);
                }
                response.setHeader("Content-Length", size + "");
                downloadSize = Long.valueOf(size);
            }
            RandomAccessFile in = null;
            OutputStream out = null;
            try {
                in = new RandomAccessFile(String.valueOf(downloadSize), "rw");
                // 设置下载起始位置
                if (fromPos > 0) {
                    in.seek(fromPos);
                }
                // 缓冲区大小
                int bufLen = (int) (downloadSize < 2048 ? downloadSize : 2048);
                byte[] buffer = new byte[bufLen];
                int num;
                int count = 0; // 当前写到客户端的大小
                out = response.getOutputStream();
                while ((num = in.read(buffer)) != -1) {
                    out.write(buffer, 0, num);
                    count += num;
                    //处理最后一段，计算不满缓冲区的大小
                    if (downloadSize - count < bufLen) {
                        bufLen = (int) (downloadSize - count);
                        if (bufLen == 0) {
                            break;
                        }
                        buffer = new byte[bufLen];
                    }
                }
                out.write(content);
                out.flush();
                out.close();
                response.flushBuffer();
                return JsonUtil.getSuccessJsonObject();
            } catch (IOException e) {
                System.out.println("数据被暂停或中断");
            } finally {
                if (null != out) {
                    try {
                        out.close();
                    } catch (IOException e) {
                        System.out.println("数据被暂停或中断");
                    }
                }
                if (null != in) {
                    try {
                        in.close();
                    } catch (IOException e) {
                        System.out.println("数据被暂停或中断");
                    }
                }
            }
        }
        return JsonUtil.getSuccessJsonObject();
    }


    @ApiOperation("deleteFile")
    @RequestMapping(value = "/deleteFile", method = RequestMethod.POST)
    public JSONObject deleteFile(@RequestParam("fileId") String fileId) {
        File file = fileService.selectById(fileId);
        if (file == null) return JsonUtil.getFailJsonObject(localeMessageSourceService.getMessage("fileIsEmpty"));
        fileService.deleteById(fileId);
        dfsClient.deleteFile(file.getFileUrl());
        return JsonUtil.getSuccessJsonObject();
    }

    @ApiOperation("deleteFiles")
    @RequestMapping(value = "/deleteFiles", method = RequestMethod.POST)
    public JSONObject deleteFiles(@RequestParam("fileIds") String fileIds) {
        List<String> fileIdList= StrUtil.getStringListByString(fileIds,",");
        for (String fileId : fileIdList) {
            File file = fileService.selectById(fileId);
            if (file == null) return JsonUtil.getFailJsonObject(localeMessageSourceService.getMessage("fileIsEmpty"));
            fileService.deleteById(fileId);
            dfsClient.deleteFile(file.getFileUrl());
        }
        return JsonUtil.getSuccessJsonObject();
    }
    @ApiOperation("删除文件夹")
    @PostMapping("delFolder")
    public JSONObject delFolder(@RequestParam("id") Long id) {
        Folder folder = folderService.selectById(id);
        if (folder == null) return JsonUtil.getFailJsonObject("文件夹不存在,请刷新后重试");
        File file = new File();
        file.setFolderId(id);
        List<File> files = fileService.selectList(file);
        if (!ArrayUtil.isEmpty(files)) {
            List<String> strs = files.stream().map(s -> s.getId()).collect(Collectors.toList());
            String req = "";
            req = req.join(",", strs);
            JSONObject res = deleteFiles(req);
        }
        folderService.deleteById(id);
        return JsonUtil.getSuccessJsonObject("删除成功");
    }
    @ApiOperation("新建文件夹")
    @PostMapping("createFolder")
    public JSONObject createFolder(@RequestHeader("companyId") Long companyId,
                                   @RequestHeader("username") String username,
                                   @RequestParam("parentId") Long parentId,
                                   @RequestParam("name") String name) {


        Folder child = new Folder();
        if(parentId!=0){
            Folder folder = new Folder();
            folder.setId(parentId);
            Folder res = folderService.selectOne(folder);
            if (res == null) return JsonUtil.getFailJsonObject("请选择父级菜单");
            child.setProjectId(res.getProjectId());
            child.setParentId(res.getId());
            child.setParentIds(res.getParentIds() + "," + res.getId());
            child.setFullPath(res.getFullPath() + name + "/");
            child.setCreateBy(username);
            child.setName(name);
        }else{
            child.setProjectId(companyId);
            child.setParentId(0L);
            child.setParentIds("0");
            child.setFullPath("/" + name + "/");
            child.setCreateBy(username);
            child.setName(name);
        }

        Integer num = folderService.insertSelective(child);
        if (num == 1) return JsonUtil.getSuccessJsonObject("新建成功");
        return JsonUtil.getFailJsonObject("新建失败");
    }

    @ApiOperation("查询树形结构")
    @GetMapping("/getTree")
    public JSONObject getTree(@RequestParam("projectId") Long projectId) {
        Map<String, Object> map = new HashMap<>();
        map.put("projectId", projectId);
        map.put("parentId", 0);
        List<FolderVO> folderVOList = folderService.getTree(map);
        return JsonUtil.getSuccessJsonObject(folderVOList);
    }

}
